home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
VELENG10.ZIP
/
EVALUATE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-27
|
50KB
|
2,192 lines
// ****************************************************************************
// * *
// * Velena Source Code V1.0 *
// * Written by Giuliano Bertoletti *
// * Based on the knowledged approach of Louis Victor Allis *
// * Copyright (C) 1996-97 by Giuliano Bertoletti & GBE 32241 Software PR *
// * *
// ****************************************************************************
// Portable engine version.
// read the README file for further informations.
// ==========================================================================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include <math.h>
#include "connect4.h"
#include "con4vals.h"
#include "rules.h"
#include "pnsearch.h"
#include "proto.h"
/* Prototypes */
/* That should not be removed in order to get the correct pointer size */
struct threat_combo {
short cross,even,odd;
short gp1,gp2;
};
char **allocate_matrix(struct board *board);
char *who[]={"None","White (O)","Black (X)"};
char *eng[]={"Draw","won by White","won by Black"};
/* Program */
char *rulename[]={"CLAIMEVEN",
"BASEINVERSE",
"VERTICAL",
"AFTEREVEN",
"LOWINVERSE",
"HIGHINVERSE",
"BASECLAIM",
"BEFORE",
"SPECIALBEFORE"};
/* --------------------------------------------------------------- */
void show_square_used(struct board *board)
{
short x,y;
for(y=0;y<BOARDY;y++)
{
for(x=0;x<BOARDX;x++)
{
if(board->sqused[ELM(x,BOARDY-y-1)]) printf("*");
else printf(".");
}
printf("\n");
}
}
void test_conditions(char **matrix,struct board *board)
{
short x,y,z,n1,n2,x1,y1;
printf("Enter rule 1 number : ");
scanf("%d %d",&x,&y);
printf("\n\r\n\r");
if(x>=0 && x<board->sp && y>=0 && y<board->sp)
{
n1=board->solution[x]->solname;
n2=board->solution[y]->solname;
printf("Rule %d: ",x);
printf("%13s ",rulename[n1-1]);
printf("--> %c%d-%c%d ",ELX(board->solution[x]->solpoint[0])+65,
ELY(board->solution[x]->solpoint[0])+1,
ELX(board->solution[x]->solpoint[1])+65,
ELY(board->solution[x]->solpoint[1])+1);
for(z=0;z<board->solution[x]->sqinvnumb;z++)
printf("%c%d ",ELX(board->solution[x]->sqinv[z])+97,
ELY(board->solution[x]->sqinv[z])+1);
printf("\n\r");
printf("Rule %d: ",y);
printf("%13s ",rulename[n2-1]);
printf("--> %c%d-%c%d ",ELX(board->solution[y]->solpoint[0])+65,
ELY(board->solution[y]->solpoint[0])+1,
ELX(board->solution[y]->solpoint[1])+65,
ELY(board->solution[y]->solpoint[1])+1);
for(z=0;z<board->solution[y]->sqinvnumb;z++)
printf("%c%d ",ELX(board->solution[y]->sqinv[z])+97,
ELY(board->solution[y]->sqinv[z])+1);
printf("\n\r");
printf("\n\r");
x1=x;
y1=y;
if(y1>x1)
{
x1=y;
y1=x;
}
if(matrix[x1][y1])
{
printf("They seem to be compatible :-)))\n\r\n\r");
}
else
{
printf("They don't seem to be compatible :-(((\n\r\n\r");
}
}
else
{
printf("Rules %d,%d don't exist!\n\r\n\r");
}
}
void update_log(struct board *board)
{
time_t t;
short x;
FILE *h1;
h1=fopen(LOGFILE,"a+");
if(!h1) fatal_error("Cannot open logfile");
time(&t);
fprintf(h1,"%s",ctime(&t));
fprintf(h1,"Game played: ");
for(x=0;x<board->filled;x++)
putc(board->moves[x]+0x31,h1);
fprintf(h1," (%d moves)",board->filled);
fprintf(h1," %s\n",eng[board->lastwin]);
fprintf(h1,"\n");
fclose(h1);
}
void dump_file_threat(struct board *board,short anythreat)
{
short px1,px2,py1,py2;
FILE *h1;
h1=fopen(LOGFILE,"a+");
if(!h1) fatal_error("Cannot open logfile");
px1=board->xplace[anythreat][0];
py1=board->yplace[anythreat][0];
px2=board->xplace[anythreat][3];
py2=board->yplace[anythreat][3];
fprintf(h1,"Group taken as odd threat for white is %c%d-%c%d\n\n",px1+97,py1+1,px2+97,py2+1);
fclose(h1);
}
void dump_file_board(struct board *board)
{
short x,y,z;
FILE *h1;
h1=fopen(LOGFILE,"a+");
if(!h1) fatal_error("Cannot write to logfile");
fprintf(h1,"------------------------------------------------------------------------\n\n");
fprintf(h1,"Current board status: ");
for(x=0;x<board->filled;x++)
fputc(board->moves[x]+0x31,h1);
fprintf(h1,"\n\n");
for(y=BOARDY-1;y>=0;y--)
{
for(x=0;x<BOARDX;x++)
{
z=board->square[ELM(x,y)];
if(z==EMPTY) fprintf(h1," .");
else if(z==WHITE) fprintf(h1," O");
else fprintf(h1," X");
}
fprintf(h1,"\n\n");
}
fprintf(h1,"%s is to move\n",who[board->turn]);
fclose(h1);
}
/***************************************************************************/
short odd_threat(struct board *board,short x)
{
short y,empty=0,fill=0,emp[TILES],px,py;
for(y=0;y<TILES;y++)
{
if(*board->groups[x][y]==EMPTY)
{
px=board->xplace[x][y];
py=board->yplace[x][y];
emp[empty++]=ELM(px,py);
}
else if (*board->groups[x][y]==WHITE) fill++;
}
if(empty==1 && fill==3 && (py&1)==0 && board->stack[px]<py) return emp[0];
return -1;
}
void wipe_above(struct board *board,short sq)
{
short x,y,z;
x=ELX(sq);
y=ELY(sq);
for(z=y;z<BOARDY;z++)
board->wipesq[ELM(x,z)]=1;
}
void wipe_odd(struct board *board,short sq)
{
short x,y,z,ye;
x=ELX(sq);
y=(board->stack[x]&0x0e)+2;
ye=ELY(sq);
for(z=y;z<=ye;z+=2)
board->wipesq[ELM(x,z)]=1;
}
short wiped_group(struct board *board,short group)
{
short x,px,py;
for(x=0;x<TILES;x++)
{
px=board->xplace[group][x];
py=board->yplace[group][x];
if(board->wipesq[ELM(px,py)]) return YES;
}
return NO;
}
short check_threat(struct board *board,short px,short i,short side)
{
short x,y,p1,p2,fx,fy,j;
for(y=0;y<board->solvable_groups->sqpnt[ELM(px,i)];y++)
{
j=board->solvable_groups->square[ELM(px,i)][y];
if(board->xplace[j][0]==board->xplace[j][3]) continue;
p1=0;
p2=0;
for(x=0;x<TILES;x++)
{
fx=board->xplace[j][x];
fy=board->yplace[j][x];
if(board->square[ELM(fx,fy)]==side) p1++;
else if (board->square[ELM(fx,fy)]==EMPTY) p2++;
}
if(p1+p2==TILES) return YES;
}
return NO;
}
short check_men(struct board *board,short group,short side)
{
short x,y,p1=0,p2=0,fx,fy;
for(x=0;x<TILES;x++)
{
fx=board->xplace[group][x];
fy=board->yplace[group][x];
if(board->square[ELM(fx,fy)]==side) p1++;
else if (board->square[ELM(fx,fy)]==EMPTY) p2++;
}
return ((p1+p2==4)?p1:-1);
}
short check_even_below(struct board *board,short square,short side)
{
short px,py,i;
px=ELX(square);
py=ELY(square);
for(i=1;i<py;i+=2)
if(board->square[ELM(px,i)]==EMPTY && check_threat(board,px,i,side))
return YES;
return NO;
}
short count_odd_threats(struct board *board,short *threats)
{
short x,y,oddpnt=0;
for(x=0;x<GROUPS;x++)
{
y=odd_threat(board,x);
if(y!=-1) threats[oddpnt++]=y;
}
return oddpnt;
}
/* --------------------------------------------------------------- */
void both_groups(struct board *board,short q1,short q2)
{
short x,y,p1,p2,g1,g2;
p1=board->solvable_groups->sqpnt[q1];
p2=board->solvable_groups->sqpnt[q2];
for(x=0;x<p1;x++)
for(y=0;y<p2;y++)
{
g1=board->solvable_groups->square[q1][x];
g2=board->solvable_groups->square[q2][y];
if(g1==g2 && board->intgp.tgroups[g1])
board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=g1;
}
}
short recurse_groups(struct board *board,short cols,short *cl,short gp)
{
short p,i,g1,g2;
p=board->solvable_groups->sqpnt[cl[0]];
for(i=0;i<p;i++)
{
g1=board->solvable_groups->square[cl[0]][i];
if(cols==1 && g1==gp) return YES;
else if(g1==gp && recurse_groups(board,cols-1,&cl[1],g1)) return YES;
}
return NO;
}
void both_many_groups(struct board *board,short cols,short *cl)
{
short p,i,g1;
if(cols==0) return;
p=board->solvable_groups->sqpnt[cl[0]];
for(i=0;i<p;i++)
{
g1=board->solvable_groups->square[cl[0]][i];
if(!board->intgp.tgroups[g1]) continue;
if(cols==1 || recurse_groups(board,cols-1,&cl[1],g1))
board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=g1;
}
}
void solve_columns(struct board *board,short cl,short *cols)
{
short i,j,k,t,answer;
short px,py,tx,ty;
for(i=0;i<GROUPS;i++)
{
if(board->intgp.tgroups[i]!=YES) continue;
answer=YES;
for(j=0;j<cl && answer;j++)
{
answer=NO;
px=ELX(cols[j]);
py=ELY(cols[j]);
for(k=0;k<TILES && !answer;k++)
{
if(*board->groups[i][k]==EMPTY &&
px==board->xplace[i][k] &&
py<=board->yplace[i][k]) answer=YES;
}
}
if(j==cl && answer)
{
if(board->solution[board->sp]->solgroupsnumb==0)
{
board->solution[board->sp]->sqinvnumb=2*cl;
for(t=0;t<cl;t++)
{
tx=ELX(cols[t]);
ty=ELY(cols[t]);
board->solution[board->sp]->sqinv[t ]=ELM(tx,ty-1);
board->solution[board->sp]->sqinv[t+cl]=ELM(tx,ty);
}
}
board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=i;
}
}
}
void check_claim(struct board *board,short *cl)
{
short x,y,z;
short px,py;
px=ELX(cl[1]);
py=ELY(cl[1])+1;
if(py<BOARDY && (py&1)==1)
{
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=BASECLAIM;
board->solution[board->sp]->sqinv[0]=cl[0];
board->solution[board->sp]->sqinv[1]=cl[1];
board->solution[board->sp]->sqinv[2]=cl[2];
board->solution[board->sp]->sqinv[3]=ELM(px,py);
board->solution[board->sp]->sqinvnumb=4;
board->solution[board->sp]->solpoint[0]=cl[0];
board->solution[board->sp]->solpoint[1]=ELM(px,py);
both_groups(board,cl[0],ELM(px,py));
board->instances[BASECLAIM]++;
if(board->solution[board->sp]->solgroupsnumb>0)
{
both_groups(board,cl[1],cl[2]);
board->sp++;
}
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=BASECLAIM;
board->solution[board->sp]->sqinv[0]=cl[0];
board->solution[board->sp]->sqinv[1]=cl[1];
board->solution[board->sp]->sqinv[2]=cl[2];
board->solution[board->sp]->sqinv[3]=ELM(px,py);
board->solution[board->sp]->sqinvnumb=4;
board->solution[board->sp]->solpoint[0]=ELM(px,py);
board->solution[board->sp]->solpoint[1]=cl[2];
both_groups(board,ELM(px,py),cl[2]);
board->instances[BASECLAIM]++;
if(board->solution[board->sp]->solgroupsnumb>0)
{
both_groups(board,cl[0],cl[1]);
board->sp++;
}
}
}
void generate_all_other_before_instances(struct board *board,short cols,short *cl,short j)
{
short cnt=0,step,pn[4];
short gc[4][3],sl[4][2];
short x,y,px,py,flag,px1,px2,py1,py2;
step=(128>>cols);
for(x=0;x<cols;x++)
{
px=ELX(cl[x]);
py=ELY(cl[x]);
gc[x][2]=cl[x];
gc[x][1]=ELM(px,py-1);
if(board->stack[px]<=py-2) gc[x][0]=ELM(px,py-2);
else gc[x][0]=-1;
}
while(cnt<128)
{
pn[0]=(cnt>>6)&1;
pn[1]=(cnt>>5)&1;
pn[2]=(cnt>>4)&1;
pn[3]=(cnt>>3)&1;
for(x=0;x<cols;x++)
{
sl[x][1]=gc[x][1+pn[x]];
sl[x][0]=gc[x][0+pn[x]];
}
flag=YES;
for(x=0;x<cols && flag;x++)
if(sl[x][0]==-1) flag=FALSE;
for(y=0;y<2 && flag;y++)
for(x=0;x<cols && flag;x++)
if(board->sqused[sl[x][y]]==NO) flag=FALSE;
if(flag)
{
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=BEFORE;
board->solution[board->sp]->solpoint[0]=ELM(board->xplace[j][0],board->yplace[j][0]);
board->solution[board->sp]->solpoint[1]=ELM(board->xplace[j][3],board->yplace[j][3]);
board->solution[board->sp]->sqinvnumb=2*cols;
for(x=0;x<2*cols;x++)
board->solution[board->sp]->sqinv[x]=sl[x>>1][x&1];
for(x=0;x<cols;x++)
{
py2=ELY(sl[x][1]);
if((py2&1)==1) both_many_groups(board,1,&sl[x][1]);
else both_groups(board,sl[x][0],sl[x][1]);
}
both_many_groups(board,cols,cl);
board->instances[BEFORE]++;
if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
}
cnt+=step;
}
}
/* ******************************************************************** */
/* ******************************************************************** */
void check_double_threat(struct board *board,short x,short y,
struct threat_combo *tch,short *pnt)
{
short j,k,wx,pq,w1,w2,px,py,g1,g2,jg,kg;
pq=ELM(x,y);
for(j=0;j<board->solvable_groups->sqpnt[pq]-1;j++)
for(k=j+1;k<board->solvable_groups->sqpnt[pq];k++)
{
jg=board->solvable_groups->square[pq][j];
kg=board->solvable_groups->square[pq][k];
w1=check_men(board,jg,WHITE);
w2=check_men(board,kg,WHITE);
if(w1!=2 || w2!=2) continue;
for(wx=0;wx<TILES;wx++)
{
px=board->xplace[jg][wx];
py=board->yplace[jg][wx];
if(*board->groups[jg][wx]==EMPTY && (px!=x || py!=y))
g1=ELM(px,py);
}
for(wx=0;wx<TILES;wx++)
{
px=board->xplace[kg][wx];
py=board->yplace[kg][wx];
if(*board->groups[kg][wx]==EMPTY && (px!=x || py!=y))
g2=ELM(px,py);
}
if(ELX(g1)==ELX(g2) && abs(ELY(g1)-ELY(g2))==1)
{
tch[*pnt].cross=pq;
if((ELY(g1)&1)==1)
{
tch[*pnt].even=g1;
tch[*pnt].odd =g2;
}
else
{
tch[*pnt].odd =g1;
tch[*pnt].even=g2;
}
tch[*pnt].gp1=jg;
tch[*pnt].gp2=kg;
(*pnt)++;
}
}
}
short threat_combo(struct board *board,struct threat_combo *tc)
{
short x,y,z=0;
/* The common square must be odd */
for(y=2;y<BOARDY;y+=2)
for(x=0;x<BOARDX;x++)
if(board->stack[x]<y) check_double_threat(board,x,y,tc,&z);
return z;
}
/* --------------------------------------------------------------- */
void wipe_many_groups(struct board *board,short cols,short *cl)
{
short p,i,g1;
if(cols==0) return;
p=board->solvable_groups->sqpnt[cl[0]];
for(i=0;i<p;i++)
{
g1=board->solvable_groups->square[cl[0]][i];
if(!board->usablegroup[g1]) continue;
if(cols==1 || recurse_groups(board,cols-1,&cl[1],g1))
board->usablegroup[g1]=NO;
}
}
void handle_even_above_odd(struct board *board,struct threat_combo *tc)
{
short x,y,y1,y2,px,py,qx,qy,sx,sy;
short cl[2];
/* Rule one */
wipe_odd(board,tc->cross);
/* Rule two */
px=ELX(tc->cross);
py=ELY(tc->cross)+1;
qx=ELX(tc->odd);
qy=ELY(tc->odd)+1;
for(y1=qy;y1<BOARDY;y1++)
for(y2=py;y2<BOARDY;y2++)
{
cl[0]=ELM(qx,y1);
cl[1]=ELM(px,y2);
wipe_many_groups(board,2,cl);
}
/* Rule three */
cl[0]=tc->odd;
cl[1]=ELM(ELX(tc->cross),ELY(tc->cross)+1);
wipe_many_groups(board,2,cl);
/* Rule four */
if(board->stack[qx]==ELY(tc->odd))
{
sx=px;
sy=py+1;
wipe_above(board,ELM(sx,sy));
}
/* Rule five */
if((board->stack[px]&1)==0 && board->stack[qx]<(qy-1))
{
cl[0]=ELM(px,board->stack[px]);
cl[1]=ELM(qx,board->stack[qx]);
wipe_many_groups(board,2,cl);
}
/* Rule six */
qx=ELX(tc->odd);
qy=board->stack[qx];
for(y=qy;y<BOARDY-1;y++)
{
cl[0]=ELM(qx,y);
cl[1]=ELM(qx,y+1);
wipe_many_groups(board,2,cl);
}
}
void handle_odd_above_even(struct board *board,struct threat_combo *tc)
{
short x,y,y1,y2,px,py,qx,qy;
short cl[2];
/* Rule one */
wipe_odd(board,tc->cross);
/* Rule two */
px=ELX(tc->cross);
py=ELY(tc->cross)+1;
qx=ELX(tc->even);
qy=ELY(tc->even)+1;
for(y1=qy;y1<BOARDY;y1++)
for(y2=py;y2<BOARDY;y2++)
{
cl[0]=ELM(qx,y1);
cl[1]=ELM(px,y2);
wipe_many_groups(board,2,cl);
}
/* Rule three */
if((board->stack[px]&1)==0 && board->stack[qx]<(qy-1))
{
cl[0]=ELM(px,board->stack[px]);
cl[1]=ELM(qx,board->stack[qx]);
wipe_many_groups(board,2,cl);
}
/* Rule four */
qx=ELX(tc->odd);
qy=board->stack[qx];
for(y=qy;y<BOARDY-1;y++)
{
cl[0]=ELM(qx,y);
cl[1]=ELM(qx,y+1);
wipe_many_groups(board,2,cl);
}
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
void claimeven(struct board *board)
{
short x1,y1,q1,q2;
short sln,*grp,j,k;
for(y1=1;y1<BOARDY;y1+=2)
for(x1=0;x1<BOARDX;x1++)
{
if(!board->sqused[ELM(x1,y1)]) continue;
board->solution[board->sp]->solgroupsnumb=0;
q1=ELM(x1,y1);
q2=ELM(x1,y1-1);
if(board->square[q1]==EMPTY &&
board->square[q2]==EMPTY && board->sqused[q2])
{
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
if(board->intgp.tgroups[grp[j]]==YES)
{
if(board->solution[board->sp]->solgroupsnumb==0)
{
board->solution[board->sp]->solname=CLAIMEVEN;
board->solution[board->sp]->solpoint[0]=q1;
board->solution[board->sp]->solpoint[1]=q2;
board->solution[board->sp]->sqinv[0]=q1;
board->solution[board->sp]->sqinv[1]=q2;
board->solution[board->sp]->sqinvnumb=2;
board->instances[CLAIMEVEN]++;
}
board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=grp[j];
}
}
if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
}
}
void baseinverse(struct board *board)
{
short x1,y1,q1,q2,px,py,wx,wy;
short sln,*grp,j,k,x,y;
char set[64];
for(y1=0;y1<BOARDY;y1++)
for(x1=0;x1<BOARDX;x1++)
{
q1=ELM(x1,y1);
if(!board->sqused[q1]) continue;
if(board->stack[x1]==y1)
{
memset(set,YES,64);
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.tgroups[grp[j]]==YES)
{
for(x=0;x<TILES;x++)
{
wx=board->xplace[grp[j]][x];
wy=board->yplace[grp[j]][x];
if(x1<wx && board->stack[wx]==wy &&
set[ELM(wx,wy)] && board->sqused[ELM(wx,wy)])
{
set[ELM(wx,wy)]=NO;
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=BASEINVERSE;
board->solution[board->sp]->solpoint[0]=q1;
board->solution[board->sp]->solpoint[1]=ELM(wx,wy);
board->solution[board->sp]->sqinv[0]=q1;
board->solution[board->sp]->sqinv[1]=ELM(wx,wy);
board->solution[board->sp]->sqinvnumb=2;
both_groups(board,q1,ELM(wx,wy));
board->instances[BASEINVERSE]++;
if(board->solution[board->sp]->solgroupsnumb>0)
board->sp++;
}
}
}
}
}
}
}
void vertical(struct board *board)
{
short x1,y1,q1,wy;
short sln,*grp,j,x;
char set[64];
for(y1=0;y1<BOARDY;y1++)
for(x1=0;x1<BOARDX;x1++)
{
q1=ELM(x1,y1);
if(!board->sqused[q1]) continue;
if(board->square[q1]==EMPTY)
{
memset(set,YES,64);
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.tgroups[grp[j]]==YES &&
board->xplace[grp[j]][0]==board->xplace[grp[j]][3])
{
for(x=0;x<TILES;x++)
{
wy=board->yplace[grp[j]][x];
if(wy>0 && (wy&1)==0 && y1==wy-1 &&
set[ELM(x1,wy)] && board->sqused[ELM(x1,wy)])
{
set[ELM(x1,wy)]=NO;
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=VERTICAL;
board->solution[board->sp]->solpoint[0]=q1;
board->solution[board->sp]->solpoint[1]=ELM(x1,wy);
board->solution[board->sp]->sqinv[0]=q1;
board->solution[board->sp]->sqinv[1]=ELM(x1,wy);
board->solution[board->sp]->sqinvnumb=2;
both_groups(board,q1,ELM(x1,wy));
board->instances[VERTICAL]++;
if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
}
}
}
}
}
}
}
void aftereven(struct board *board)
{
short x1,y1,q1,px,py,aftereven;
short sln,*grp,j,x,cols,cl[4],pj;
for(y1=1;y1<BOARDY;y1+=2)
for(x1=0;x1<BOARDX;x1++)
{
q1=ELM(x1,y1);
if(!board->sqused[q1]) continue;
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.mygroups[grp[j]]==YES &&
x1==board->xplace[grp[j]][0] &&
x1<board->xplace[grp[j]][3])
{
aftereven=YES;
cols=0;
memset(cl,0xff,8);
for(x=0;x<TILES && aftereven;x++)
{
px=board->xplace[grp[j]][x];
py=board->yplace[grp[j]][x];
if(board->sqused[ELM(px,py)]==NO) aftereven=NO;
if(board->square[ELM(px,py)]==EMPTY)
{
if((py&1)==1 && board->stack[px]<=py-1)
cl[cols++]=ELM(px,py);
else aftereven=NO;
}
}
if(aftereven && cols>0)
{
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=AFTEREVEN;
board->solution[board->sp]->solpoint[0]=q1;
board->solution[board->sp]->solpoint[1]=ELM(board->xplace[grp[j]][3],board->yplace[grp[j]][3]);
board->instances[AFTEREVEN]++;
board->solution[board->sp]->sqinvnumb=cols;
for(pj=0;pj<cols;pj++)
board->solution[board->sp]->sqinv[pj]=cl[pj];
solve_columns(board,cols,cl);
if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
}
}
}
}
}
void lowinverse(struct board *board)
{
short x1,y1,q1,q2,px,py,wx,wy;
short sln,*grp,j,k,x,y;
char set[64];
for(y1=2;y1<BOARDY;y1+=2)
for(x1=0;x1<BOARDX;x1++)
{
q1=ELM(x1,y1);
if(!board->sqused[q1]) continue;
if(board->stack[x1]<y1)
{
memset(set,YES,64);
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.tgroups[grp[j]]==YES &&
board->xplace[grp[j]][0]!=board->xplace[grp[j]][3])
{
for(x=0;x<TILES;x++)
{
wx=board->xplace[grp[j]][x];
wy=board->yplace[grp[j]][x];
if(x1<wx && board->stack[wx]<wy && wy>0 &&
(wy&1)==0 && set[ELM(wx,wy)] &&
board->sqused[ELM(wx,wy)])
{
set[ELM(wx,wy)]=NO;
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=LOWINVERSE;
board->solution[board->sp]->solpoint[0]=q1;
board->solution[board->sp]->solpoint[1]=ELM(wx,wy);
board->solution[board->sp]->sqinv[0]=q1;
board->solution[board->sp]->sqinv[1]=ELM(wx,wy);
board->solution[board->sp]->sqinv[2]=ELM(x1,y1-1);
board->solution[board->sp]->sqinv[3]=ELM(wx,wy-1);
board->solution[board->sp]->sqinvnumb=4;
both_groups(board,q1,ELM(wx,wy));
both_groups(board,q1,ELM(x1,y1-1));
both_groups(board,ELM(wx,wy),ELM(wx,wy-1));
board->instances[LOWINVERSE]++;
if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
}
}
}
}
}
}
}
void highinverse(struct board *board)
{
short x1,y1,q1,q2,px,py,wx,wy;
short sln,*grp,j,k,x,y;
char set[64];
for(y1=2;y1<BOARDY;y1+=2)
for(x1=0;x1<BOARDX;x1++)
{
q1=ELM(x1,y1);
if(!board->sqused[q1]) continue;
if(board->stack[x1]<y1)
{
memset(set,YES,64);
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.tgroups[grp[j]]==YES &&
board->xplace[grp[j]][0]!=board->xplace[grp[j]][3])
{
for(x=0;x<TILES;x++)
{
wx=board->xplace[grp[j]][x];
wy=board->yplace[grp[j]][x];
if(x1<wx && board->stack[wx]<wy && wy>0 &&
(wy&1)==0 && set[ELM(wx,wy)] &&
board->sqused[ELM(wx,wy)])
{
set[ELM(wx,wy)]=NO;
board->solution[board->sp]->solgroupsnumb=0;
board->solution[board->sp]->solname=HIGHINVERSE;
board->solution[board->sp]->solpoint[0]=q1;
board->solution[board->sp]->solpoint[1]=ELM(wx,wy);
board->solution[board->sp]->sqinv[0]=q1;
board->solution[board->sp]->sqinv[1]=ELM(wx,wy);
board->solution[board->sp]->sqinv[2]=ELM(x1,y1-1);
board->solution[board->sp]->sqinv[3]=ELM(wx,wy-1);
board->solution[board->sp]->sqinv[4]=ELM(x1,y1+1);
board->solution[board->sp]->sqinv[5]=ELM(wx,wy+1);
board->solution[board->sp]->sqinvnumb=6;
board->instances[HIGHINVERSE]++;
/* Upper and middle squares */
both_groups(board,ELM(x1,y1+1),ELM(wx,wy+1));
both_groups(board,q1,ELM(wx,wy));
/* Vertical groups */
both_groups(board,ELM(x1,y1),ELM(x1,y1+1));
both_groups(board,ELM(wx,wy),ELM(wx,wy+1));
/* Lower 1st and Upper 2nd if lower is playable */
if(board->stack[x1]==y1-1)
both_groups(board,ELM(x1,y1-1),ELM(wx,wy+1));
/* Upper 1st and Lower 2nd if lower is playable */
if(board->stack[wx]==wy-1)
both_groups(board,ELM(x1,y1+1),ELM(wx,wy-1));
if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
}
}
}
}
}
}
}
void baseclaim(struct board *board)
{
short x1,y1,q1,q2,px,py,wx,wy;
short sln,*grp,j,k,x,y,cl[6],cols;
char set[64];
memset(set,YES,64);
for(y1=0;y1<BOARDY;y1++)
for(x1=0;x1<BOARDX;x1++)
{
if(!board->sqused[ELM(x1,y1)]) continue;
if(board->stack[x1]==y1)
{
q1=ELM(x1,y1);
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.tgroups[grp[j]]==YES &&
board->xplace[grp[j]][0]!=board->xplace[grp[j]][3])
{
cols=0;
for(x=0;x<TILES;x++)
{
wx=board->xplace[grp[j]][x];
wy=board->yplace[grp[j]][x];
if(board->sqused[ELM(wx,wy)]==0) continue;
if(board->stack[wx]==wy) cl[cols++]=ELM(wx,wy);
}
if(cols!=3) continue;
else
{
cl[3]=cl[1];
cl[4]=cl[0];
if(set[cl[0]]) check_claim(board,&cl[0]);
set[cl[0]]=NO;
} }
}
}
}
}
void before(struct board *board)
{
short j,px,py,before;
short x,cols,cl[TILES];
for(j=0;j<GROUPS;j++)
{
if(!board->intgp.mygroups[j] ||
board->xplace[j][0]==board->xplace[j][3] ||
board->yplace[j][0]==BOARDY-1 ||
board->yplace[j][3]==BOARDY-1) continue;
cols=0;
before=YES;
for(x=0;x<TILES && before;x++)
{
px=board->xplace[j][x];
py=board->yplace[j][x];
if(!board->sqused[ELM(px,py)]) before=NO;
else if(board->square[ELM(px,py)]==EMPTY)
cl[cols++]=ELM(px,py+1);
}
if(before && cols>0)
{
for(x=0;x<cols;x++)
board->solution[board->sp]->sqinv[x]=cl[x];
generate_all_other_before_instances(board,cols,cl,j);
}
}
}
/*
void before(struct board *board)
{
short x1,y1,q1,px,py,before,pj,fx,fy;
short sln,*grp,j,x,cols,cl[TILES];
for(y1=0;y1<BOARDY;y1++)
for(x1=0;x1<BOARDX;x1++)
{
q1=ELM(x1,y1);
if(!board->sqused[q1]) continue;
sln=board->solvable_groups->sqpnt[q1];
grp=board->solvable_groups->square[q1];
for(j=0;j<sln;j++)
{
if(board->intgp.mygroups[grp[j]]==YES &&
x1==board->xplace[grp[j]][0] &&
x1<board->xplace[grp[j]][3])
{
before=YES;
cols=0;
memset(cl,0xff,8);
for(x=0;x<TILES && before;x++)
{
px=board->xplace[grp[j]][x];
py=board->yplace[grp[j]][x];
if(board->square[ELM(px,py)]==EMPTY)
{
if(py<BOARDY-1) cl[cols++]=ELM(px,py+1);
else before=NO;
}
}
if(before && cols>0)
{
for(pj=0;pj<cols;pj++)
board->solution[board->sp]->sqinv[pj]=cl[pj];
generate_all_other_before_instances(board,cols,cl,grp[j]);
}
}
}
}
}
/* --------------------------------------------------------------- */
short threat_group(struct board *board,short group,short who)
{
short p;
p=((*board->groups[group][0])|(*board->groups[group][1])|
(*board->groups[group][2])|(*board->groups[group][3]));
if(p&who) return NO;
return YES;
}
/* -------------------------------------------------------------------- */
short check_early_win(struct board *board)
{
if(board->square[SQ_d1]==WHITE &&
board->square[SQ_c3]==WHITE &&
board->square[SQ_e3]==WHITE &&
(board->square[SQ_c2]==WHITE || board->square[SQ_e2]==WHITE) &&
board->square[SQ_b2]==EMPTY &&
board->square[SQ_d2]==EMPTY &&
board->square[SQ_f2]==EMPTY) return YES;
return NO;
}
short anypentas(struct board *board)
{
short an=0;
if(board->square[SQ_c1]!=WHITE && board->square[SQ_e1]!=WHITE) return 0;
if(board->square[SQ_b3]==WHITE &&
board->square[SQ_d3]==WHITE &&
(board->square[SQ_b2]==WHITE || board->square[SQ_d2]==WHITE) &&
board->square[SQ_a2]==EMPTY &&
board->square[SQ_c2]==EMPTY &&
board->square[SQ_e2]==EMPTY) an|=2;
if(board->square[SQ_d3]==WHITE &&
board->square[SQ_f3]==WHITE &&
(board->square[SQ_d2]==WHITE || board->square[SQ_f2]==WHITE) &&
board->square[SQ_c2]==EMPTY &&
board->square[SQ_e2]==EMPTY &&
board->square[SQ_g2]==EMPTY) an|=1;
return an;
}
void dump_instances(struct board *board)
{
short x,y,i,px1,py1,px2,py2;
for(x=1;x<=9;x++)
{
printf("%13s ",rulename[x-1]);
for(y=0;y<board->sp;y++)
{
if(board->solution[y]->solname==x)
{
px1=ELX(board->solution[y]->solpoint[0]);
py1=ELY(board->solution[y]->solpoint[0]);
px2=ELX(board->solution[y]->solpoint[1]);
py2=ELY(board->solution[y]->solpoint[1]);
printf("(%c%d,%c%d) ",px1+65,py1+1,px2+65,py2+1);
}
}
printf("\n\r");
}
}
void ss_dump_instances(struct board *board,FILE *h1)
{
short x,y,i,px1,py1,px2,py2;
for(x=1;x<=9;x++)
{
fprintf(h1,"%13s ",rulename[x-1]);
for(y=0;y<board->sp;y++)
{
if(board->solution[y]->solname==x)
{
px1=ELX(board->solution[y]->solpoint[0]);
py1=ELY(board->solution[y]->solpoint[0]);
px2=ELX(board->solution[y]->solpoint[1]);
py2=ELY(board->solution[y]->solpoint[1]);
fprintf(h1,"(%c%d,%c%d) ",px1+65,py1+1,px2+65,py2+1);
}
}
fprintf(h1,"\n\r");
}
}
void dump_solutions(struct board *board,short sol)
{
short x,y,px1,px2,py1,py2,gp,k,found=0;
FILE *h1;
h1=fopen(LOGFILE,"a+");
if(!h1) fatal_error("Cannot open logfile");
printf("\n\r");
printf("%s\n\r",rulename[sol-1]);
fprintf(h1,"\n");
fprintf(h1,"%s\n",rulename[sol-1]);
for(x=0;x<board->sp;x++)
{
if(board->solution[x]->solname==sol)
{
found++;
px1=ELX(board->solution[x]->solpoint[0]);
py1=ELY(board->solution[x]->solpoint[0]);
px2=ELX(board->solution[x]->solpoint[1]);
py2=ELY(board->solution[x]->solpoint[1]);
printf("(%c%d,%c%d) [%3d]--> ",px1+65,py1+1,px2+65,py2+1,x);
fprintf(h1,"(%c%d,%c%d) [%3d]--> ",px1+65,py1+1,px2+65,py2+1,x);
for(y=0;y<board->solution[x]->solgroupsnumb;y++)
{
gp=board->solution[x]->solgroups[y];
px1=board->xplace[gp][0];
py1=board->yplace[gp][0];
px2=board->xplace[gp][3];
py2=board->yplace[gp][3];
printf("%c%d%c%d ",px1+97,py1+1,px2+97,py2+1);
fprintf(h1,"%c%d%c%d ",px1+97,py1+1,px2+97,py2+1);
}
printf("\n\r");
fprintf(h1,"\n");
for(k=0;k<board->solution[x]->sqinvnumb;k++)
{
gp=board->solution[x]->sqinv[k];
printf("%c%d ",ELX(gp)+97,ELY(gp)+1);
fprintf(h1,"%c%d ",ELX(gp)+97,ELY(gp)+1);
}
printf("\n\r");
fprintf(h1,"\n");
}
}
printf("\n\r");
fprintf(h1,"\n");
printf("Total solution found of specified kind: %d\n\r",found);
fprintf(h1,"Total solution found of specified kind: %d\n",found);
printf("Output end.\n\r");
fclose(h1);
}
void debug_black(struct board *board)
{
short key,oracle;
register x;
char **matrix;
short i,*bpos;
board->sp=0;
board->intgp.j=0;
board->intgp.k=0;
memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
for(i=0;i<GROUPS;i++)
{
if(threat_group(board,i,BLACK))
{
board->intgp.tgroups[i]=YES;
board->intgp.j++;
}
else board->intgp.tgroups[i]=NO;
if(threat_group(board,i,WHITE))
{
board->intgp.mygroups[i]=YES;
board->intgp.k++;
}
else board->intgp.mygroups[i]=NO;
}
claimeven(board);
baseinverse(board);
vertical(board);
aftereven(board);
lowinverse(board);
highinverse(board);
baseclaim(board);
before(board);
dump_instances(board);
dump_file_board(board);
matrix=(char **)allocate_matrix(board);
build_adjacency_matrix(matrix,board);
oracle=problem_solver(board,matrix,NO,NULL);
printf("\n\r");
printf("Total sol. found : %d, total dangerous groups %d, groups solved %d\n\r",
board->sp,board->intgp.j,board->problem_solved);
printf("Oracle spits out %d\n\r",oracle);
printf("Key 1 - 9 to see rules instances, ESC to return to game play\n\r");
printf("j to dump the non adjacencies, t to test rule compatibility\n\r");
while((key=readkey())!=0x1b)
{
switch(key)
{
case '1':
dump_solutions(board,CLAIMEVEN);
break;
case '2':
dump_solutions(board,BASEINVERSE);
break;
case '3':
dump_solutions(board,VERTICAL);
break;
case '4':
dump_solutions(board,AFTEREVEN);
break;
case '5':
dump_solutions(board,LOWINVERSE);
break;
case '6':
dump_solutions(board,HIGHINVERSE);
break;
case '7':
dump_solutions(board,BASECLAIM);
break;
case '8':
dump_solutions(board,BEFORE);
break;
case '9':
dump_solutions(board,SPECIALBEFORE);
break;
case 'j':
dump_no_adjacencies(matrix,board);
break;
case 't':
test_conditions(matrix,board);
break;
}
}
free_matrix(matrix,board);
}
void debug_white(struct board *board)
{
short x,y,x1,y1,f,g,j;
struct threat_combo tc[GROUPS];
short threats[GROUPS],thnumb,anythreat=0,ccmb;
short key,oracle,combo,pentas;
char **matrix;
short i,*bpos,px,py;
if(check_early_win(board))
{
printf("An early win is detected! (ESC to return)\n\r");
while(readkey()!=0x1b);
return;
}
pentas=0;
combo=threat_combo(board,tc);
thnumb=count_odd_threats(board,threats);
if(thnumb+combo==0 && !pentas)
{
printf("No decisive threats, (ESC to return)\n\r");
while(readkey()!=0x1b);
return;
}
do
{
memset(board->usablegroup,0xff,GROUPS*sizeof(short));
memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
memset(board->wipesq,0x00,(BOARDX+1)*(BOARDY+2)*sizeof(short));
if(anythreat<thnumb)
{
wipe_above(board,threats[anythreat]);
wipe_odd(board,threats[anythreat]);
px=ELX(threats[anythreat]);
for(py=0;py<BOARDY;py++)
if(board->square[ELM(px,py)]==EMPTY)
board->sqused[ELM(px,py)]=NO;
}
else if(anythreat<thnumb+combo)
{
ccmb=anythreat-thnumb;
px=ELX(tc[ccmb].cross);
x =ELX(tc[ccmb].odd);
for(y=0;y<BOARDY;y++)
{
if(board->square[ELM(px,y)]==EMPTY)
board->sqused[ELM(px,y)]=NO;
if(board->square[ELM( x,y)]==EMPTY)
board->sqused[ELM( x,y)]=NO;
}
if(ELY(tc[ccmb].even)>ELY(tc[ccmb].odd))
handle_even_above_odd(board,&tc[ccmb]);
else handle_odd_above_even(board,&tc[ccmb]);
}
else fatal_error("What am I doing?");
board->sp=0;
board->intgp.j=0;
board->intgp.k=0;
for(i=0;i<GROUPS;i++)
{
if(threat_group(board,i,WHITE) &&
!wiped_group(board,i) && board->usablegroup[i])
{
board->intgp.tgroups[i]=YES;
board->intgp.j++;
}
else board->intgp.tgroups[i]=NO;
if(threat_group(board,i,BLACK))
{
board->intgp.mygroups[i]=YES;
board->intgp.k++;
}
else board->intgp.mygroups[i]=NO;
}
claimeven(board);
baseinverse(board);
vertical(board);
aftereven(board);
lowinverse(board);
highinverse(board);
baseclaim(board);
before(board);
dump_instances(board);
dump_file_board(board);
if(anythreat<thnumb) dump_file_threat(board,anythreat);
matrix=(char **)allocate_matrix(board);
build_adjacency_matrix(matrix,board);
oracle=problem_solver(board,matrix,NO,NULL);
printf("\n\r");
printf("Total sol. found : %d, total dangerous groups %d, groups solved %d\n\r",
board->sp,board->intgp.j,board->problem_solved);
if(anythreat<thnumb)
{
printf("Odd threat at %c%d, oracle spits out %d\n\r",
ELX(threats[anythreat])+97,ELY(threats[anythreat])+1,oracle);
}
else if(anythreat<thnumb+combo)
{
printf("Double odd threat at %c%d, oracle spits out %d\n\r",
ELX(tc[anythreat-thnumb].cross)+97,ELY(tc[anythreat-thnumb].cross)+1,oracle);
}
else
{
printf("Pentas found.\n\r",pentas);
}
printf("1 - 9 to see rules instances, ESC to return to game play\n");
printf("j to dump the non adjacencies, t to test rule compatibility\n");
printf("s to show squares available\n");
while((key=readkey())!=0x1b)
{
switch(key)
{
case '1':
dump_solutions(board,CLAIMEVEN);
break;
case '2':
dump_solutions(board,BASEINVERSE);
break;
case '3':
dump_solutions(board,VERTICAL);
break;
case '4':
dump_solutions(board,AFTEREVEN);
break;
case '5':
dump_solutions(board,LOWINVERSE);
break;
case '6':
dump_solutions(board,HIGHINVERSE);
break;
case '7':
dump_solutions(board,BASECLAIM);
break;
case '8':
dump_solutions(board,BEFORE);
break;
case '9':
dump_solutions(board,SPECIALBEFORE);
break;
case 'j':
dump_no_adjacencies(matrix,board);
break;
case 't':
test_conditions(matrix,board);
break;
case 's':
show_square_used(board);
break;
}
}
free_matrix(matrix,board);
anythreat++;
} while(anythreat<thnumb+combo || pentas);
}
void debug_function(struct board *board)
{
clrscr();
switch(board->turn)
{
case WHITE:
debug_black(board);
break;
case BLACK:
debug_white(board);
break;
}
}
/* -------------------------------------------------------------------- */
// Main evaluation function for the oracle
short evaluate_black(struct board *board)
{
short key,oracle;
register x;
char **matrix;
short i,*bpos;
board->sp=0;
board->intgp.j=0;
board->intgp.k=0;
memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
for(i=0;i<GROUPS;i++)
{
if(threat_group(board,i,BLACK))
{
board->intgp.tgroups[i]=YES;
board->intgp.j++;
}
else board->intgp.tgroups[i]=NO;
if(threat_group(board,i,WHITE))
{
board->intgp.mygroups[i]=YES;
board->intgp.k++;
}
else board->intgp.mygroups[i]=NO;
}
claimeven(board);
baseinverse(board);
vertical(board);
aftereven(board);
lowinverse(board);
highinverse(board);
baseclaim(board);
before(board);
if(board->intgp.j==0) return YES;
if(board->sp==0) return NO;
matrix=(char **)allocate_matrix(board);
build_adjacency_matrix(matrix,board);
oracle=problem_solver(board,matrix,NO,NULL);
free_matrix(matrix,board);
return oracle;
}
short evaluate_white(struct board *board)
{
short x,y;
struct threat_combo tc[GROUPS];
short threats[MAXGROUPS],thnum=0,combo,ccmb;
short key,oracle,anythreat=0;
char **matrix;
short i,*bpos,px,py;
combo=threat_combo(board,tc);
thnum=count_odd_threats(board,threats);
if(thnum+combo==0) return NO;
do
{
memset(board->usablegroup,0xff,GROUPS*sizeof(short));
memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
memset(board->wipesq,0x00,(BOARDX+1)*(BOARDY+2)*sizeof(short));
if(anythreat<thnum)
{
wipe_above(board,threats[anythreat]);
wipe_odd(board,threats[anythreat]);
px=ELX(threats[anythreat]);
for(py=0;py<BOARDY;py++)
if(board->square[ELM(px,py)]==EMPTY)
board->sqused[ELM(px,py)]=NO;
}
else
{
ccmb=anythreat-thnum;
px=ELX(tc[ccmb].cross);
x =ELX(tc[ccmb].odd);
for(y=0;y<BOARDY;y++)
{
if(board->square[ELM(px,y)]==EMPTY)
board->sqused[ELM(px,y)]=NO;
if(board->square[ELM( x,y)]==EMPTY)
board->sqused[ELM( x,y)]=NO;
}
if(ELY(tc[ccmb].even)>ELY(tc[ccmb].odd))
handle_even_above_odd(board,&tc[ccmb]);
else
handle_odd_above_even(board,&tc[ccmb]);
}
board->sp=0;
board->intgp.j=0;
board->intgp.k=0;
for(i=0;i<GROUPS;i++)
{
if(threat_group(board,i,WHITE) &&
!wiped_group(board,i) && board->usablegroup[i])
{
board->intgp.tgroups[i]=YES;
board->intgp.j++;
}
else board->intgp.tgroups[i]=NO;
if(threat_group(board,i,BLACK))
{
board->intgp.mygroups[i]=YES;
board->intgp.k++;
}
else board->intgp.mygroups[i]=NO;
}
for(y=0;y<BOARDY;y++)
for(x=0;x<BOARDX;x++)
if(board->square[ELM(x,y)]!=EMPTY &&
board->sqused[ELM(x,y)]==NO)
fatal_error("Marked as used an useless square...");
claimeven(board);
baseinverse(board);
vertical(board);
aftereven(board);
lowinverse(board);
highinverse(board);
baseclaim(board);
before(board);
if(board->intgp.j==0) oracle=YES;
else if(board->sp==0) oracle=NO;
else
{
matrix=(char **)allocate_matrix(board);
build_adjacency_matrix(matrix,board);
oracle=problem_solver(board,matrix,NO,NULL);
free_matrix(matrix,board);
}
anythreat++;
} while(anythreat<thnum+combo && oracle==NO);
return oracle;
}
short evaluation_function(struct board *board)
{
switch(board->turn)
{
case WHITE:
return evaluate_black(board);
case BLACK:
return evaluate_white(board);
}
return NOCOMMENT;
}
// *************************************************************************
// Single step evaluation to file
short ss_evaluate_black(struct board *board)
{
FILE *h1;
short key,oracle;
register x;
char **matrix;
short i,*bpos;
h1=fopen(TMPFILENAME,"w");
if(!h1) fatal_error("Cannot open temporary file");
fprintf(h1,"Oracle analysis for red:\n\n");
board->sp=0;
board->intgp.j=0;
board->intgp.k=0;
memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
for(i=0;i<GROUPS;i++)
{
if(threat_group(board,i,BLACK))
{
board->intgp.tgroups[i]=YES;
board->intgp.j++;
}
else board->intgp.tgroups[i]=NO;
if(threat_group(board,i,WHITE))
{
board->intgp.mygroups[i]=YES;
board->intgp.k++;
}
else board->intgp.mygroups[i]=NO;
}
fprintf(h1,"There are %d groups in which red can connect four men and ",board->intgp.j);
fprintf(h1,"%d dangerous\ngroups in which yellow can connect four men.\n",board->intgp.k);
fprintf(h1,"\n");
claimeven(board);
baseinverse(board);
vertical(board);
aftereven(board);
lowinverse(board);
highinverse(board);
baseclaim(board);
before(board);
if(board->intgp.j==0)
{
fprintf(h1,"This implies that at least a draw is guaranteed.\n");
oracle=YES;
goto BSS_ENDING;
}
if(board->sp==0)
{
fprintf(h1,"No rules can be applied to solve the aforementioned groups in which\n");
fprintf(h1,"yellow can connect four men. Therefore nothing can be said about red.\n");
oracle=NO;
goto BSS_ENDING;
}
fprintf(h1,"Total number of rule instances is: %d\n\n",board->sp);
matrix=(char **)allocate_matrix(board);
build_adjacency_matrix(matrix,board);
oracle=problem_solver(board,matrix,YES,h1);
free_matrix(matrix,board);
BSS_ENDING:
fprintf(h1,"\n");
fclose(h1);
return oracle;
}
short ss_evaluate_white(struct board *board)
{
FILE *h1;
short x,y;
struct threat_combo tc[GROUPS];
short threats[MAXGROUPS],thnum=0,combo,ccmb;
short key,oracle,anythreat=0;
char **matrix;
short i,*bpos,px,py;
h1=fopen(TMPFILENAME,"w");
if(!h1) fatal_error("Cannot open temporary file");
fprintf(h1,"Oracle analysis for yellow:\n\n");
combo=threat_combo(board,tc);
thnum=count_odd_threats(board,threats);
if(thnum+combo==0)
{
fprintf(h1,"There are no single or double threats for yellow\n");
fprintf(h1,"therefore nothing can be said about yellow possibilities\n");
oracle=NO;
goto WSS_ENDING;
}
fprintf(h1,"There are %d odd threats and %d double threats for yellow\n\n",
thnum,combo);
do
{
for(x=0;x<75;x++)
fputc('*',h1);
fprintf(h1,"\n\nCase #%d: ",anythreat+1);
memset(board->usablegroup,0xff,GROUPS*sizeof(short));
memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
memset(board->wipesq,0x00,(BOARDX+1)*(BOARDY+2)*sizeof(short));
if(anythreat<thnum)
{
fprintf(h1,"odd threat at %c%d.\n\n",
ELX(threats[anythreat])+'a',ELY(threats[anythreat])+1);
wipe_above(board,threats[anythreat]);
wipe_odd(board,threats[anythreat]);
px=ELX(threats[anythreat]);
for(py=0;py<BOARDY;py++)
if(board->square[ELM(px,py)]==EMPTY)
board->sqused[ELM(px,py)]=NO;
}
else
{
ccmb=anythreat-thnum;
px=ELX(tc[ccmb].cross);
x =ELX(tc[ccmb].odd);
fprintf(h1,"double threat at %c%d.\n\n",
ELX(tc[ccmb].cross)+'a',ELY(tc[ccmb].cross)+1);
for(y=0;y<BOARDY;y++)
{
if(board->square[ELM(px,y)]==EMPTY)
board->sqused[ELM(px,y)]=NO;
if(board->square[ELM( x,y)]==EMPTY)
board->sqused[ELM( x,y)]=NO;
}
if(ELY(tc[ccmb].even)>ELY(tc[ccmb].odd))
handle_even_above_odd(board,&tc[ccmb]);
else
handle_odd_above_even(board,&tc[ccmb]);
}
board->sp=0;
board->intgp.j=0;
board->intgp.k=0;
fprintf(h1,"Eliminating squares: ");
for(x=0;x<BOARDX;x++)
for(y=0;y<BOARDY;y++)
if(!board->sqused[ELM(x,y)])
fprintf(h1,"%c%d ",x+'a',y+1);
fprintf(h1,"\n\n");
for(i=0;i<GROUPS;i++)
{
if(threat_group(board,i,WHITE) &&
!wiped_group(board,i) && board->usablegroup[i])
{
board->intgp.tgroups[i]=YES;
board->intgp.j++;
}
else board->intgp.tgroups[i]=NO;
if(threat_group(board,i,BLACK))
{
board->intgp.mygroups[i]=YES;
board->intgp.k++;
}
else board->intgp.mygroups[i]=NO;
}
for(y=0;y<BOARDY;y++)
for(x=0;x<BOARDX;x++)
if(board->square[ELM(x,y)]!=EMPTY &&
board->sqused[ELM(x,y)]==NO)
fatal_error("Marked as used an useless square...");
fprintf(h1,"There are %d group(s) in which yellow can connect four men and ",board->intgp.j);
fprintf(h1,"%d dangerous\ngroup(s) in which red can connect four men.\n",board->intgp.k);
fprintf(h1,"\n");
claimeven(board);
baseinverse(board);
vertical(board);
aftereven(board);
lowinverse(board);
highinverse(board);
baseclaim(board);
before(board);
if(board->intgp.j==0)
{
fprintf(h1,"This implies that a win is guaranteed.\n");
oracle=YES;
}
else if(board->sp==0)
{
fprintf(h1,"No rules can be applied to solve the aforementioned groups in which\n");
fprintf(h1,"red can connect four men. Therefore nothing can be said about yellow.\n");
oracle=NO;
}
else
{
fprintf(h1,"Total number of rule instances is: %d\n\n",board->sp);
matrix=(char **)allocate_matrix(board);
build_adjacency_matrix(matrix,board);
oracle=problem_solver(board,matrix,YES,h1);
free_matrix(matrix,board);
}
fprintf(h1,"\n");
anythreat++;
} while(anythreat<thnum+combo && oracle==NO);
if(oracle==YES && anythreat<thnum+combo)
{
fprintf(h1,"No further cases are taken into consideration since\n");
fprintf(h1,"this last case is sufficient to prove yellow can win\n");
fprintf(h1,"from this position.\n");
}
WSS_ENDING:
fprintf(h1,"\n");
fclose(h1);
return oracle;
}
short ss_evaluation_function(struct board *board)
{
switch(board->turn)
{
case WHITE:
return ss_evaluate_black(board);
case BLACK:
return ss_evaluate_white(board);
}
return NOCOMMENT;
}